Proc mi nezafunguje try->finally v threadu?
Otázka od: Martin Krim
1. 10. 2004 17:24
> > Muzete mi, prosim, nekdo rict, proc... kdyz mam nejakou botu v procedure
> Proved se mi nezobrazi zadne chyba (vetsinou aplikace jen tise zamrzne) a
> kdyz nezamrzne, tak cely ten thread nejakym zpusobem zhavaruje a neprovede
> se ani ta cast toho finally.
IMHO, kazde vlakno ma svuj vlastni zasobnik a vyjimky se vzdy siri po
zasobniku, tedy volanim metody Synchronize presmerujete vykonani metody
Proved do hlavniho vlakna programu, tedy k vyvolani vyjimky by melo dojit v
hlavnim vlakne programu a za pokus by stalo zkusit implementovat obsluhu
udalosti TApplication.OnException a pokusit se tak zachytit vyjimku - BTW,
pomoci teto udalosti muzete zachytavat vsechny neosetrene vyjimky (z
hlavniho vlakna programu) a vypsat uzivateli neco jako
"Omlouvame se za
zpusobene potize......".
Martin Krim
Odpovedá: Slavomir Skopalik
1. 10. 2004 9:50
Ta konstrukce je ponekud divna.
Jaky mela mit ucel ?
Zkus si dat break point do sekce finally, mel to normalne funguje.
Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
windows W9x, kde padne cela aplikace do BSOD).
Takze doporucuji misto finally pouzit except, a dobre promyslet
ten suspend (ze by preklep ?).
Slavek
> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;
>
> Muzete mi, prosim, nekdo rict, proc... kdyz mam nejakou botu
> v procedure Proved se mi nezobrazi zadne chyba (vetsinou
> aplikace jen tise zamrzne) a kdyz nezamrzne, tak cely ten
> thread nejakym zpusobem zhavaruje a neprovede se ani ta cast
> toho finally. PROC? Diky Jirka
Odpovedá: Ing. Jiri Sokol
1. 10. 2004 15:00
> Od: Slavomir Skopalik <skopalik@elektlabs.cz>
> Datum: 01.10.2004 11:16:56
>
> Ta konstrukce je ponekud divna.
> Jaky mela mit ucel ?
> Zkus si dat break point do sekce finally, mel to normalne funguje.
> Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
> windows W9x, kde padne cela aplikace do BSOD).
> Takze doporucuji misto finally pouzit except, a dobre promyslet
> ten suspend (ze by preklep ?).
>
> Slavek
V tom threadu mam kod, ktery se v urcitych intervalech, po slpneni urcitych
podminek opakuje - ridi hlavni thread aplikace volanim Resume threadu. Jakmile
ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi pozadavek
spusteni.
Ze se mi to chova nekorektne jsem zjistil napr tim, ze jsem mel preklep v kodu,
ktery mi prekladac nenasel a sice:
Vlakno:=TThread(nil); //tady mi vypadlo ".Create"
Vlakno.Params.Clear; //<-- tady se to kousne beze slova... aplikace se tvari,
ze v pohode bezi...
atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho "Proved" zhuci na
vyjimku - bohuzel "zatim" nepisu kod bez chyb. Proto jsem to dal do toho bloku
try->finally a doufal, ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal pokracovat...
bohuzel se tak nedeje. V kodu pouzivam komponenty TIBDatabase, TIBTransaction,
TIBDataset, TIBQuery - nekde jsem vycetl, ze IB/FB neni tzv. "thread safety" a
tak si vsechny spojeni na databazi vytvarim v tele Create toho threadu. Doufam,
ze to s tim nesouvisi...
Diky za dalsi pomoc
Jirka
Odpovedá: Ing. Jiri Sokol
1. 10. 2004 15:20
> Od: Ing. Jiri Sokol <js-delphi@email.cz>
> Datum: 01.10.2004 15:23:43
>
> > Od: Slavomir Skopalik <skopalik@elektlabs.cz>
> > Datum: 01.10.2004 11:16:56
> >
> > Ta konstrukce je ponekud divna.
> > Jaky mela mit ucel ?
> > Zkus si dat break point do sekce finally, mel to normalne funguje.
> > Jestli vznikne vyjimka v threadu, tak ten se ukonci (vyjimkou jsou
> > windows W9x, kde padne cela aplikace do BSOD).
> > Takze doporucuji misto finally pouzit except, a dobre promyslet
> > ten suspend (ze by preklep ?).
> >
> > Slavek
>
Omlouvam se, ale v mem predchozim prispevku jsem udelal chybu... -> Posilam
opraveny text. Dekuju za pochopeni.
V tom threadu mam kod, ktery se v urcitych intervalech, po slpneni urcitych
podminek opakuje - ridi hlavni thread aplikace volanim Resume threadu. Jakmile
ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi pozadavek
spusteni.
Ze se mi to chova nekorektne jsem zjistil napr tim, ze jsem mel preklep v kodu,
ktery mi prekladac nenasel a sice:
!!!! CHYBA v minulem mailu, omlouvam se... (*> Vlakno:=TThread(nil); //tady mi
vypadlo ".Create" *)
melo byt:
VlaknoTran:=TIBTransaction(nil); //tady mi vypadlo ".Create"
VlaknoTran.Params.Clear; //<-- tady se to kousne beze slova... aplikace se
tvari, ze v pohode bezi...
pricemz VlaknoTran je interni promenna toho threadu.
atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho "Proved" zhuci na
vyjimku - bohuzel "zatim" nepisu kod bez chyb. Proto jsem to dal do toho bloku
try->finally a doufal, ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal pokracovat...
Nicmene i na podle me primitivnim prikladu, ktery se snad (bez urazky) muzu
stat komukoliv, do bloku finally nedojde... PROC????
bohuzel se tak nedeje. V kodu pouzivam komponenty TIBDatabase, TIBTransaction,
TIBDataset, TIBQuery - nekde jsem vycetl, ze IB/FB neni tzv. "thread safety" a
tak si vsechny spojeni na databazi vytvarim v tele Create toho threadu. Doufam,
ze to s tim nesouvisi...
Diky za dalsi pomoc a omlouvam se za predchozi mystifikaci
Jirka
Odpovedá: Petr Vones
1. 10. 2004 17:04
From: "Ing. Jiri Sokol" <js-delphi@email.cz>
> Ahoj, mam asi trivialni dotaz, ale nevim si s nim rady.
> Ma cca takovou konstrukci
> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;
To je dost nestastna konstrukce. Takove veci je vhodnejsi resit nejakym
eventem na ktery cekas a nevolat Suspend.
Petr Vones
Odpovedá: Petr Fejfar
1. 10. 2004 17:35
Ing. Jiri Sokol wrote:
> Mam cca takovou konstrukci
> procedure TMainThread.Execute;
> begin
> while not Terminated do
> try
> Synchronize(proved);
> finally
> if not Terminated then Suspend;
> end;//try->finally
> end;
Cert vi, co se ti tam vlastne deje <g>
Jestli totiz mas takovouhle konstrukci, tak se zamysli na tim,
proc vubec vytvaris thread, protoze pokud spoustis
ten vypocet pres synchronize, tak se metoda "proved" vykona v kontextu
*hlavniho* threadu a tvuj TMainThread bude cekat na jeho dokonceni !!!
Cili to bude horsi, nez kdybys to zavolal rovnou z hlavniho threadu
***
To synchronize pracuje v principu takto:
* V kontextu podruzneho threadu volani Synchronize() zaradi "proved" do
fronty
spolu s event pro indikaci konce vypoctu a zavola WakeMainThread(),
coz typicky zpusobi postnuti zpravy WM_NULL instanci TApplication.
* Pak podruzny thread ceka na stav signaled te predane event
tj. na konec vypoctu
* Po prijmu zpravy WM_NULL v kontextu *hlavniho* threadu instance
TApplication
pres volani CheckSynchronize() vyzvedne "proved" z fronty a spusti ho
* Az "proved" skonci, tak se signalizuje konec vypoctu pres event, coz
vzbudi
podruzny thread a ten pokracuje dal.
***
BTW, to je taky odpoved na to, proc treba v prikladu, na ktery te odkazoval
TOndrej nekdy pred mesicem, se synchronize nepouziva: chces-li totiz mit
slusny multiprocessing, musis zapomenout na "siditka" jako synchronize
a navrhnout si vlastni plnohodnotny IPC.
HTH, pf
Odpovedá: Petr Vones
1. 10. 2004 16:56
From: "Ing. Jiri Sokol" <js-delphi@email.cz>
> Jakmile ta urcita cast kodu skonci, ma se thread "uspat" a cekat na dalsi
> pozadavek spusteni.
Jenze pokud vykonavas cely ten kod tak, ze jej cely volas prostrednictvim
metody TThread.Synchornize, tak nema smysl aby tam ten thread byl. Tim to
volani totiz stejne provedes v kontextu hlavniho threadu.
Petr Vones
Odpovedá: Slavomir Skopalik
1. 10. 2004 17:10
> Vlakno:=TThread(nil); //tady mi vypadlo ".Create"
> Vlakno.Params.Clear; //<-- tady se to kousne beze slova...
> aplikace se tvari, ze v pohode bezi...
>
> atd. Pak se mi nekde stane, ze mi nejaka cast kodu toho
> "Proved" zhuci na vyjimku - bohuzel "zatim" nepisu kod bez
> chyb. Proto jsem to dal do toho bloku try->finally a doufal,
> ze kdyz mi to v tom kodu zhuci, dostane se to do bloku
> finally a aplikace zahlasi chybu, ke ktere doslo, a bude dal
> pokracovat...
Aplikace zadnou chybu nezahlasi, ta je "preposlana" prislusnemu threadu
a tam ti chybi jeji obslouzeni.
>
> bohuzel se tak nedeje. V kodu pouzivam komponenty
> TIBDatabase, TIBTransaction, TIBDataset, TIBQuery - nekde
> jsem vycetl, ze IB/FB neni tzv. "thread safety" a tak si
> vsechny spojeni na databazi vytvarim v tele Create toho
> threadu. Doufam, ze to s tim nesouvisi...
Tak jak je to napsane, klidne muzes thready smazat,
aplikace bude fungovat o neco (tisicin promile) tychleji.
Slavek
Odpovedá: Petr Fejfar
1. 10. 2004 17:47
Martin Krim wrote:
> a za pokus by stalo zkusit
> implementovat obsluhu udalosti TApplication.OnException
Tak to ne - synchronizovana metoda se spousti ve funkci
CheckSynchronization()
a pripadna vyjimka je zachycena pomoci try-expect a jeji instance prirazena
do property
TThread.SynchronizeException.
pf
Odpovedá: Slavomir Skopalik
1. 10. 2004 20:29
>
> IMHO, kazde vlakno ma svuj vlastni zasobnik a vyjimky se vzdy
> siri po zasobniku, tedy volanim metody Synchronize
> presmerujete vykonani metody Proved do hlavniho vlakna
> programu, tedy k vyvolani vyjimky by melo dojit v hlavnim
Jenze je to trochu jinak, doporucuji se podivat do kodu
funkce CheckSynchronize(Timeout: Integer = 0): Boolean;
specialne na tuto cast:
try
SyncProc.SyncRec.FMethod;
except
SyncProc.SyncRec.FSynchronizeException :=
AcquireExceptionObject;
end;
Zde je jasne videt, ze pripadna vyjimka bude zachycena a ulozena !
Pak nasleduje jiz v kontextu prislusneho vlakna tento kod:
if Assigned(ASyncRec.FSynchronizeException) then raise
ASyncRec.FSynchronizeException;
Tim ovsem dojde ke zniceni zasobniku (pokud pouzivate JCL) , ale
vyjimka je hozena ve vlakna .
Slavek
> vlakne programu a za pokus by stalo zkusit implementovat
> obsluhu udalosti TApplication.OnException a pokusit se tak
> zachytit vyjimku - BTW, pomoci teto udalosti muzete
> zachytavat vsechny neosetrene vyjimky (z hlavniho vlakna
> programu) a vypsat uzivateli neco jako
"Omlouvame se za
> zpusobene potize......".